#include "stm32f10x.h"                  // Device header

enum Key_Warning_Type
{
    Key_Warning_Accurate = 0,                // 数据精准标志位 0.准  1.不准 使用三次异或实现，如果三次全一样则为
    Key_Warning_Inaccurate                   
};

enum Key_Value_Type
{
    Key_Value_Pressed = 0,                    // 按键值     1.松开 0.按下
    Key_Value_Released,
    Key_Value_NoEvent          
};

enum Key_State_Type
{
    Key_State_0 = 0,                          // 按键状态 0.无 1.检测消抖 
    Key_State_1
};

enum Event_Val_Type
{
    Event_Val_ShortPress = 0,                    // 短按
    Event_Val_LongPress,                         // 长按
    Event_Val_DoublePress,                       // 双按
    Event_Val_NoEvent                            // 无事件
};

enum Event_State_Type
{
    Event_State_0 = 0,                 // 状态0
    Event_State_1                      // 状态1
};

uint8_t Key_Warning = Key_Warning_Accurate;         // 数据精准标志位 0.准  1.不准 使用三次异或实现，如果三次全一样则为
uint8_t Key_Value = Key_Value_Released;             // 按键值        1.松开 0.按下
uint8_t Key_Value_Old = Key_Value_Released;         // 上一次按键值
uint8_t Key_Value_Sum = 0;                          // 按键值累加
uint8_t Key_Count = 0;                              // 按键计数 1 - 3
uint8_t Key_State = Key_State_0;                    // 按键状态 0.无 1.检测消抖 

uint8_t Event_Val = Event_Val_NoEvent;              // 事件状态值 0.短按 1.长按 2.双按 3.无事件

uint8_t Event_State = Event_State_0;                // 事件状态阶段 0.无 1.检测
uint16_t Event_Count = 0;                           // 200次为1s

void Key_Init(void)
{
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); //1. Peripheral 2. Write Enable

    GPIO_InitTypeDef GPIO_InitStructure = 
    {
        .GPIO_Pin = GPIO_Pin_11,
        .GPIO_Mode = GPIO_Mode_IPU,                 // 上拉输入
        .GPIO_Speed = GPIO_Speed_50MHz
    };
    GPIO_Init(GPIOB, &GPIO_InitStructure);
}

// 按键边沿检测
uint8_t Key_IF_Edge(uint8_t Key_Val, uint8_t Key_Val_Old)
{
    return Key_Val ^ Key_Val_Old;
}

/**
 * @brief   扫描按键的状态。
 * @return  表示按键状态的值：
 *              - 0：无按键事件
 *              - 1：按键按下
 *              - 2：按键松开
 *
 * @brief   Scans the state of the key.
 * @return  The value representing the key state:
 *              - 0: No key event
 *              - 1: key pressed
 *              - 2: key released
 */
uint8_t Key_Scan(void)
{
    // 保存上一个按键值
    Key_Value_Old = Key_Value;
    
    // 读取当前按键值
    Key_Value = GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_11);
    
    switch (Key_State)
    {
        case Key_State_0:
            if (Key_IF_Edge(Key_Value, Key_Value_Old))
            {
                Key_State = Key_State_1;
                Key_Count = 0;
                Key_Value_Sum = Key_Value;
                Key_Warning = Key_Warning_Accurate;
            }
            break;
        case Key_State_1:
            Key_Value_Sum += Key_Value;
            Key_Count++;
            if (Key_IF_Edge(Key_Value, Key_Value_Old))
            {
                Key_Warning = Key_Warning_Inaccurate;
            }
            if (Key_Count >= 2)
            {
                Key_State = Key_State_0;
                return (Key_Value_Sum + 1) / 3;         // 两次都是1 那么（2+1）/3 = 1 两次都是0 那么（1+1）/3 = 0 
            }
            break;
    }
    
    return Key_Value_NoEvent; // 无按键事件
}



/**
 * @brief 处理按键事件的函数
 * @param Key_Val 按键值
 * @return 事件值
 *          Event_Val_ShortPress = 0,                     短按
 *          Event_Val_LongPress,                          长按
 *          Event_Val_DoublePress,                        双按
 *          Event_Val_NoEvent                             无事件
 *
 * This function handles the key events.
 * @param Key_Val The value of the key
 * @return The event value
 * 
 * @note 如果1s内按键按下两次却不松开，返回Event_Val_ShortPress.
 */
uint8_t Key_Event(uint8_t Key_Val)
{
    switch (Event_State)
    {
        case Event_State_0:
            if (Key_Val == Key_Value_Pressed)               // 按下 (Pressed)
            {
                Event_State = Event_State_1;
                Event_Count = 1;
                Event_Val = Event_Val_NoEvent;
            }
            break;
        case Event_State_1:
            Event_Count++;
            if (Event_Count < 100)
            {
                if (Key_Val == Key_Value_Released && Event_Val == Event_Val_ShortPress)
                    {
                        Event_State = Event_State_0;
                        Event_Val = Event_Val_DoublePress;
                        return Event_Val;
                    }
                if (Key_Val == Key_Value_Released)           // 松开 (Released)
                {
                    Event_Val = Event_Val_ShortPress;
                }
            }
            else if (Event_Count < 200)
            {
                
                if (Event_Val == 0)           
                {
                    Event_State = Event_State_0;
                    return Event_Val;
                }
            }
            else
            {
                if (Key_Val == 1)           // 松开 (Released)
                {
                    Event_Val = Event_Val_LongPress;
                    Event_State = Event_State_0;
                    return Event_Val;
                }
            }
            break;
        default:
            break;
    }
    return Event_Val_NoEvent;
}
